function [y, n] = beytbill(sd, md, disc)
%BEYTBILL Bond equivalent yield for treasury bill.
%
%   Y = beytbill(SD, MD, DISC)
%
%   Inputs:
%     SD - Scalar or vector of Settlement dates in serial date or date
%          string format.
%
%     MD - Scalar or vector of Maturity dates in serial date or date
%          string format.
%
%   DISC - Discount rate in decimal format
%
%   Outputs:
%   Y - Yield in decimal format.
%
%   Note that the number of days to maturity is typically quoted as md - sd - 1.
%   A NaN (Not-a-Number) is returned for all cases in which negative prices are
%   implied by the discount rate, DISC, and the number of days between
%   settlement and maturity.
%
%   For example:
%      The settlement date of a Treasury bill is February 10, 1992, the maturity
%      date is August 6, 1992, and the discount rate is 3.89%.
%      Computing the bond equivalent yield:
%
%      y = beytbill('2/10/1992', '8/6/1992', 0.0377)
%
%      y = 0.0389
%
%   See also PRTBILL, YLDTBILL.

%   Copyright 1995-2006 The MathWorks, Inc.
%   $Revision: 1.9.2.6 $   $Date: 2009/04/15 23:07:16 $

% The bond equivalent yield satisfies one of two formulas, depending on the
% number of days, n, left to maturity. Compute n as md - sd - 1.
%
% Given Price P, Face F, and yield to maturity y:
% Case 1: n <= 182
%   P = F * 1/(1 + y/2 * (2*n/365))
%
% Case 2: 182 < n <= 365
%   P = F * 1/(1 + y/2) * 1/(1 + y/2 *(2*n/365 - 1))
%
% See Stigum & Robinson, "Money Market & Bond Calculations", Irwin
% Pages 104-105 and P = F(1 - disc*n/360)

if nargin < 3
    error('Finance:beytbill:tooFewInputs', 'Too few inputs.')
end

% Scale up the arguments and set defaults
try
    [CouponRate, Settle, Maturity] = instargbond([],sd,md);
catch E
    newE = MException('Finance:beytbill:dateInputError',...
        'Error in Settle and/or Maturity Inputs.');
    newE = addCause(newE,E);
    throw(newE)
end

if ~isnumeric(disc)
    error('Finance:prtbill:invalidDiscountValue','Discount rate must be numeric.')
end

if all(size(disc) > 1)
    error('Finance:prtbill:invalidDiscountSize','Discount rate must be scalar or vector.')
end

% Now match the previous input sizes with discount
try
   [Settle, Maturity, Discount] = finargsz('all', Settle, Maturity, disc(:));
catch E
    newE = MException('Finance:beytbill:invalidInputSize',...
        'Error in input sizes.');
    newE = addCause(newE,E);
    throw(newE)
end

% Find actual days between settlement and maturity
n = daysact(Settle, Maturity);

% Build masks for the two cases
Case1 = (n <= 182);
Case2 = ~Case1;

y = zeros(size(n));

% Compute Case1
y(Case1) = 365*Discount(Case1)./(360 - Discount(Case1).*n(Case1));

% Compute Case2 with intermediaries price, and t = n/365
price  = 1 - (Discount(Case2).*n(Case2)/360);
t = n(Case2)/365;

y(Case2) = (-2*t + 2*sqrt(t.^2 - (2*t - 1).*(1 - 1./price))) ./ (2*t - 1);